/***************************************************************************
 创建者: 华磊
 开始时间: 2019.9.20
 copyright: (C) 华友高科
 修改说明: (每次有修改就添加一条，带有 修改人，修改时间，修改描述)
 example (1) 姓名 2019.9.20 类的具体实现代码编写

 ***************************************************************************
 *  @file x.h
 *  功能:
 *
 *
 ***************************************************************************/
#ifndef MAPMANAGER_H
#define MAPMANAGER_H
#include <map>
#include <utility>
#include <algorithm>
#include <exception>
#include <atomic>
#include <vector>
#include "onemap.h"
//#include "../agv.h"
#include "common.h"
#include "noncopyable.h"
#include <queue>
//#include "../network/tcpsession.h"
//#include "../Anting/station_pos.h"

class MapDB;
class MapManager;
using MapManagerPtr = std::shared_ptr<MapManager>;
//enum
//{
//    COMMON_GROUP = 1,//普通group
//    HALT_GROUP = 2,
//    ELEVATOR_GROUP = 3
//};
//地图 由两部分助成： 点AgvStation 和 点之间的连线AgvLine
class MapManager : public noncopyable, public std::enable_shared_from_this<MapManager>
{
public:

    static MapManagerPtr getInstance()
    {
        static MapManagerPtr m_inst = MapManagerPtr(new MapManager());
        return m_inst;
     }
public:

    int checkTable();
    int getCurrentFloorId();
    int getMapVersion();
    int loadMapFromDB();//todo
    int loadMap(std::string mapPathIn);
    int getCurrentFleetMap( std::string &mapInfoReturn);
    int getFleetMap(std::string mapPathIn, std::string &mapInfoReturn);
    int writeFleetMap(std::string mapPathIn, const std::string &mapInfoIn);
    int writeFleetMap_toDb(const std::string &mapInfoIn);//todo
    //获取最优路径.有点站点到不了，一次，不知道什么原因。
    std::vector<int> getBestPath(int agv, int lastStation, int startStation, int endStation,
                                 int &distance, bool changeDirect = CAN_CHANGE_DIRECTION);
    std::vector<int> getPath_byStation(int from, int to, int &distance, int &isOkOut, bool changeDirect = CAN_CHANGE_DIRECTION);
    int getNearestReportStation(E_POSITION_TYPE poseType, double xIn, double yIn, int &stationIdOut);

public:

    MapSpirit *getMapSpiritById(int id);

    MapSpirit *getMapSpiritByName(std::string name);

    MapPath *getMapPathByStartEnd(int start, int end);

    //一个Agv占领一个站点
    int getStationFloor(int station);

    //是否同一楼层站点
    bool isSameFloorStation(int station_1, int station_2);

    //一个Agv占领一个站点
    void addOccuStation(int station, int occuAgvId);

    //线路的反向占用//这辆车行驶方向和线路方向相反
    void addOccuLine(int line, int occuAgvId);

    //如果车辆占领该站点，释放
    void freeStation(int station, int occuAgvId);

    //如果车辆在线路的占领表中，释放出去
    void freeLine(int line, int occuAgvId);

//    bool tryAddBlockOccu(std::vector<int> blocks,int agvId,int spiritId);
//    void freeBlockOccu(std::vector<int> blocks, int agvId, int spiritId);

    //获取 距离 目标点位 最近的躲避点
    int getNearestHaltStation(int agvId, int aimStation);

    bool addOccuGroup(int groupid, int agvId);
    bool freeGroup(int groupid, int agvId);

    std::vector<int> getStations(int floor);

    bool isSameFloor(int floor, int station);
    int getFloor(int spiritID);
    std::vector<int> getBlocks(int spiritID);
    std::vector<int> getGroup(int spiritID);


    int getSplineStartAngle(int pathId,double &angleOut);
    int getSplineEndAngle(int pathId,double &angleOut);
    int getSplineMiddlePosition(int pathId,double &p1xOut,double &p1yOut,double &p2xOut,double &p2yOut);
    MapPoint *getPointById(int id) { return g_onemap.getPointById(id); }
    MapPath *getPathById(int id) { return g_onemap.getPathById(id); }
    MapFloor *getFloorById(int id) { return g_onemap.getFloorById(id); }
    MapBackground *getBackgroundById(int id) { return g_onemap.getBackgroundById(id); }
    MapBlock *getBlockById(int id) { return g_onemap.getBlockById(id); }
    MapGroup *getGroupById(int id) { return g_onemap.getGroupById(id); }
    MapPath *getPathByStartEnd(int start,int end){return g_onemap.getPathByStartEnd(start,end);}

    //bool blockPassable(int blockId, int agvIdD);
    std::list<int> getOccuSpirit(int agvId);

    //用户接口
//    void interSetMap(SessionPtr conn, const Json::Value &request);
//    void interGetMap(SessionPtr conn, const Json::Value &request);

//    void interTrafficControlStation(SessionPtr conn, const Json::Value &request);
//    void interTrafficControlLine(SessionPtr conn, const Json::Value &request);
//    void interTrafficReleaseStation(SessionPtr conn, const Json::Value &request);
//    void interTrafficReleaseLine(SessionPtr conn, const Json::Value &request);

private:
    MapManager();

    //清空所有地图信息
    void clear();

    std::vector<int> getPath(int agv, int lastStation, int startStation, int endStation,
                             int &resultDistanceOut, bool changeDirect);
    std::vector<int> getPath(int from, int to, int &distanceOut, int &isOkOut,
                             bool changeDirect = CAN_CHANGE_DIRECTION);

    void getReverseLines();
    void getAdj();

    bool pathPassable(MapPath *line, int agvId);
    //判断path能够联通passable_uturnPoints
    bool pathPassable(MapPath *line, int agvId, std::vector<int> passable_uturnPoints);

private:

    OneMap g_onemap;//地图节点

    std::map<int, std::vector<int> > m_adj;// lineA -- lines{ from line A can reach which lines}
    std::map<int, std::vector<int> > m_reverseLines;

    std::map<int, std::vector<int> > line_occuagvs;//一条线路 及其上面的agv
    std::map<int, int> station_occuagv;//一个站点，及当前占用改站点的agv.没看见初始化

    std::mutex groupMtx;
    std::map<int,std::pair<int, std::vector<int> > > group_occuagv;//一个区块，及当前区块占用agv

//    std::mutex blockMtx;
//    //std::map<int,std::pair<int, std::vector<int> > > block_occuagv;//一个区块，及当前区块占用agv

    //void init_task_splitinfo();
    std::atomic_bool mapModifying;
    std::map< std::pair<int, int>, std::queue<int> > m_chd_station;
    int currentFloorId;
    MapDB *mapDb;

};

#endif // MAPMANAGER_H
